package handler

import (
	"errors"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"net/http"
	"onvif_server/api"
	"onvif_server/api/alarm"
	"onvif_server/internal/errcode"
	"onvif_server/internal/service"
	"onvif_server/pkg/ws"
	"strconv"
)

type AlarmHandler struct {
	*Handler
	alarmService service.AlarmService
	sysService   service.SystemService
}

func NewAlarmHandler(handler *Handler, alarmService service.AlarmService, sysService service.SystemService) *AlarmHandler {
	return &AlarmHandler{
		Handler:      handler,
		alarmService: alarmService,
		sysService:   sysService,
	}
}

func (h *AlarmHandler) List(ctx *gin.Context) {
	req := alarm.ListReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	total, items, err := h.alarmService.List(ctx, &req)
	api.PageData(ctx, total, items, err)
}

func (h *AlarmHandler) Delete(ctx *gin.Context) {
	req := alarm.DeleteReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	api.Response(ctx, h.alarmService.Delete(ctx, &req), nil)
}

func (h *AlarmHandler) Deatil(ctx *gin.Context) {
	id, err := strconv.ParseInt(ctx.DefaultQuery("id", ""), 10, 64)
	if err != nil || id == 0 {
		api.Fail(ctx, errcode.ErrBadRequest)
		return
	}
	res, err := h.alarmService.Detail(ctx, id)
	api.Response(ctx, err, res)
}

func (h *AlarmHandler) Create(ctx *gin.Context) {
	if ctx.ContentType() == binding.MIMEMultipartPOSTForm {
		h.RawCreate(ctx)
		return
	}
	req := alarm.CreateReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	api.Response(ctx, h.alarmService.Create(ctx, &req), nil)
}

func (h *AlarmHandler) RawCreate(ctx *gin.Context) {
	req := alarm.CreateReq{TaskId: ctx.Request.FormValue("task_id")}
	if req.TaskId == "" {
		api.Fail(ctx, errcode.ErrBadRequest)
		return
	}
	imageRes, err := h.sysService.Upload(ctx, "image")
	if err != nil {
		if !errors.Is(err, http.ErrMissingFile) {
			api.Fail(ctx, errcode.ErrServer.Wrap(err))
			return
		}
	} else {
		req.Image = imageRes.Url
	}
	videoRes, err := h.sysService.Upload(ctx, "video")
	if err != nil {
		if !errors.Is(err, http.ErrMissingFile) {
			api.Fail(ctx, errcode.ErrServer.Wrap(err))
			return
		}
	} else {
		req.Video = videoRes.Url
	}
	req.Ext = ctx.Request.FormValue("ext")
	api.Response(ctx, h.alarmService.Create(ctx, &req), nil)
}

func (h *AlarmHandler) Process(ctx *gin.Context) {
	req := alarm.ProcessReq{}
	if err := ctx.ShouldBindJSON(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	api.Response(ctx, h.alarmService.Process(ctx, &req), nil)
}

func (h *AlarmHandler) SetSetting(ctx *gin.Context) {
	req := alarm.Setting{}
	if err := ctx.ShouldBindJSON(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	api.Response(ctx, h.alarmService.SetSetting(ctx, &req), nil)
}

func (h *AlarmHandler) GetSetting(ctx *gin.Context) {
	res, err := h.alarmService.GetSetting(ctx)
	api.Response(ctx, err, res)
}

func (h *AlarmHandler) WsAlarmPopup(cid string, msg *ws.Msg) {
	h.alarmService.WsAlarmPopup(cid, msg)
}

func (h *AlarmHandler) WsAlarmPopupClose(cid string, msg *ws.Msg) {
	h.alarmService.WsAlarmPopupClose(cid, msg)
}
func (h *AlarmHandler) WsAlarmNotify(cid string, msg *ws.Msg) {
	h.alarmService.WsAlarmNotify(cid, msg)
}
